function gewRay(o,dir)
{
  if(o)
    this.origin = o.dup();
  else
    this.origin = new gewVec3();
  if(dir) 
  {
    this.direction = dir.dup();
    this.direction.normalize();
  }
  else
    this.direction = new gewVec3(); 
}
gewRay.prototype = 
{
  // Get a point on the ray with a distance from the ray's orgin
  getPointAtDistance: function(distanceFromOrigin,result)
  {
    if(!result)
      var result = new gewVec3();
    this.origin.add(this.direction.mulScalar(distanceFromOrigin,result),result);
    return result;
  },
  // Get distance between a ray and a point
  distanceToPoint:function(point)
  {
    var vecOP = gewRegVec0;
    var origin = this.origin;
    var dir = this.direction;
    point.sub(origin,vecOP);
    var length = vecOP.getLength();
    vecOP.normalize();
    var cosAlpha = dir.dot(vecOP);
    return Math.abs(length*cosAlpha);     
  },
  colisionWithPlane: function(plane,result)
  {
    var a = plane.a;
    var b = plane.b;
    var c = plane.c;
    var d = plane.d;
    var rayDir = this.direction;
    var planeN = gewRegVec0;
    planeN.set(a,b,c);
    var cosAlpha = rayDir.dot(planeN);
    // parallel to the plane (alpha=90)
    if(cosAlpha==0)
      return null;
    var deltaD = plane.distanceToPoint(this.origin);
    
    var colisitionPointDistance = -deltaD/cosAlpha;
    if(colisitionPointDistance<0)
      return null;
    if(!result)
      var result = new gewVec3();
    return this.getPointAtDistance(colisitionPointDistance,result);
  },
  colisionWithHeightMap : function(heightMap,maxDistance,step,maxError,outNormal)
  {    
    var prePoint = this.origin;
    var height = heightMap.interpolationAt(prePoint.x,prePoint.z);      
    if( prePoint.y<height) // origin is below the heightmap, should return
      return;
    var nextPoint = new gewVec3();
    var point = new gewVec3();
    for(var d=step;d<=maxDistance;d+=step)
    {
      this.getPointAtDistance(d,nextPoint);
      height = heightMap.interpolationAt(nextPoint.x,nextPoint.z);      
      if( nextPoint.y<height)
      {
        var v1 = prePoint;
        var v2 = nextPoint;
        v1.add(v2,point).divScalar(2,point);
        height = heightMap.interpolationAt(point.x,point.z);
        while( Math.abs(point.y- height) > maxError )
        {
          if(point.y>height)
            v1.set(point.x,point.y,point.z);
          else
            v2.set(point.x,point.y,point.z);
          v1.add(v2,point).divScalar(2,point);
          height = heightMap.interpolationAt(point.x,point.z);
        }
        if(outNormal)
          heightMap.getNormalAt(point.x,point.z,outNormal);
        return point;
      }
      prePoint.set(nextPoint.x,nextPoint.y,nextPoint.z);  
    }
    return null;
  },  
    /*  So lets quickly digest how this algorithm works.  First we assume that the
    origin of the ray is inside of the AABB.  If this is true,  then we know that 
    the ray MUST collide with AABB because it is contained inside of the AABB.
  
    If the origin is not inside of the AABB, then we check to see if the 
    direction the ray is heading is away from the AABB.  If it is, then it
    must NOT collide.
  
    Lastly, if the origin is outside of the AABB, and the ray is heading towards
    the AABB,  we use the length of the ray and test to see if there is an
    intersection.
  */
  colisionWithAabb:function(aabb,maxDistance)
  {
    var rayDir = this.direction;
    var rayO = this.origin;
    var mMin = aabb.min;
    var mMax = aabb.max;
    // Compute the ray delta
    var rayDelta = rayDir.mulScalar(maxDistance);
    // First we check to see if the origin of the ray is 
    // inside the AABB.  If it is, the ray intersects the AABB so 
    // we'll return true.  We start by assuming the ray origin is 
    // inside the AABB
    var inside = true;  
    // This stores the distance from either the min or max (x,y,z) to the ray's
    // origin (x,y,z) respectively, divided by the length of the ray.  The largest
    // value has the delta time of a possible intersection.
    var xt, yt, zt;    
    // Test the X component of the ray's origin to see if we are inside or not
    if(rayO.x < mMin.x)
    {
      xt = mMin.x - rayO.x;      
      if(xt > rayDelta.x) // If the ray is moving away from the AABB, there is no intersection 
        return false;      
      xt /= rayDelta.x; 
      inside = false;
    } 
    else if(rayO.x > mMax.x)
    {
      xt = mMax.x - rayO.x;      
      if(xt < rayDelta.x) // If the ray is moving away from the AABB, there is no intersection 
        return false;      
      xt /= rayDelta.x;
      inside = false;
    } 
    else
    {
      // Later on we use the "xt", "yt", and "zt" variables to determine which plane (either
      // xy, xz, or yz) we may collide with.  Since the x component of the ray
      // origin is in between, the AABB's left and right side (which reside in the yz plane), 
      // we know we don't have to test those sides so we set this to a negative value.
      xt = -1.0; 
    }
  
    // Test the Y component of the ray's origin to see if we are inside or not
    if(rayO.y < mMin.y)
    {
      yt = mMin.y - rayO.y;      
      if(yt > rayDelta.y) // If the ray is moving away from the AABB, there is no intersection 
        return false;  
      yt /= rayDelta.y;
      inside = false;
    } 
    else if(rayO.y > mMax.y)
    {
      yt = mMax.y - rayO.y;      
      if(yt < rayDelta.y) // If the ray is moving away from the AABB, there is no intersection 
        return false;      
      yt /= rayDelta.y;
      inside = false;
    } 
    else
    {
      yt = -1.0;
    }
  
    if(rayO.z < mMin.z)
    {
      zt = mMin.z - rayO.z;      
      if(zt > rayDelta.z) // If the ray is moving away from the AABB, there is no intersection 
        return false;      
      zt /= rayDelta.z;
      inside = false;
    } 
    else if(rayO.z > mMax.z)
    {
      zt = mMax.z - rayO.z;      
      if(zt < rayDelta.z) // If the ray is moving away from the AABB, there is no intersection 
        return false;      
      zt /= rayDelta.z;
      inside = false;
    } 
    else
    {
      zt = -1.0;
    }
  
    // If the origin inside the AABB
    if(inside)
      return true; // The ray intersects the AABB
    
    // Otherwise we have some checking to do...  
    // We want to test the AABB planes with largest value out of xt, yt, and zt.  So
    // first we determine which value is the largest.  
    var t = xt;    
    if(yt > t)
      t = yt;    
    if(zt > t)
      t = zt;  
    if(t == xt) // If the ray intersects with the AABB's YZ plane
    {
      // Compute intersection values
      var y = rayO.y + rayDelta.y * t;
      var z = rayO.z + rayDelta.z * t;    
      // Test to see if collision takes place within the bounds of the AABB
      if(y < mMin.y || y > mMax.y)
        return false;
      else if(z < mMin.z || z > mMax.z)
        return false;
    }
    else if(t == yt) // Intersects with the XZ plane
    {
      // Compute intersection values
      var x = rayO.x + rayDelta.x * t;
      var z = rayO.z + rayDelta.z * t;  
      // Test to see if collision takes place within the bounds of the AABB
      if(x < mMin.x || x > mMax.x)
        return false;
      else if(z < mMin.z || z > mMax.z) 
        return false;
    }
    else // Intersects with the XY plane
    {      
      // Compute intersection values
      var x = rayO.x + rayDelta.x * t;
      var y = rayO.y + rayDelta.y * t;  
      // Test to see if collision takes place within the bounds of the AABB
      if(x < mMin.x || x > mMax.x)
        return false;
      else if(y < mMin.y || y > mMax.y)
        return false;
    }  
    // The ray intersects the AABB
    return true;
  },
  // Find the nearest node that collision with this ray 
  // Return null if no node is collided
  colisionWithTreeNode: function(scene3d,maxDistance)
  {
    var quadTree = scene3d.quadTree;
    var outCells = [];
    // Get all collision cell
    quadTree.collisionWithRay(this,outCells,maxDistance);
    // Find all node have world aabb collision with this ray
    var nodes = [];
    var cellNum= outCells.length;
    var isCollision;
    for(var i =0;i<cellNum;i++)
    {
      var nodeList = outCells[i].nodeList;
      var nodeNum = nodeList.length;
      for(var n=0;n<nodeNum;n++)
      {
        var node = nodeList[n];
        if( node&&node.worldAabb )
        {
          isCollide = this.colisionWithAabb( node.worldAabb,maxDistance);
          if(isCollide)
          {
            var isAlreadyIn = isInArray(node,nodes);
            if(!isAlreadyIn)
              nodes.push(node);
          }
        } 
      }
    }
    // accurary collision test
    
    // Find nearest
    var rayO = this.origin;
    var distance = 1000000;
    var result;
    for(var i=0;i<nodes.length;i++)
    {
      var node = nodes[i];
      var nodeCenter = node.worldAabb.getCenter();
      var d = nodeCenter.sub(rayO).getLengthSquare();
      if(d<distance)
      {
        distance = d;
        result = node;
      }
    }
    return result;
  }
}
